package xj.util.gui;

import java.awt.BorderLayout;
import java.io.IOException;
import java.net.URL;
import java.util.*;

import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLFrameHyperlinkEvent;

/**
 * Html Demo
 */
public class HTMLPane extends JPanel {

  protected JEditorPane html;
  protected HTMLFrame frame;

  protected List<URL> urlList = new ArrayList<URL>();
  protected int current = -1; 

  /**
   * HtmlDemo Constructor
   */
  public HTMLPane() {
    this(null, null);
  }

  public HTMLPane(HTMLFrame frame) {
    this(frame, null);
  }

  public HTMLPane(HyperlinkListener listener) {
    this(null, listener);
  }

  public HTMLPane(HTMLFrame frame, HyperlinkListener listener) {
    this.frame = frame; 
    setLayout(new BorderLayout());
    html = new JEditorPane();
    html.setEditable(false);
    html.addHyperlinkListener(listener == null ? createHyperLinkListener(this) : listener);
    JScrollPane scroller = new JScrollPane(html);
    add(scroller, BorderLayout.CENTER);
  }

  public JEditorPane getEditorPane() { 
    return html;
  }

  public URL getCurrentURL() { 
    if (current >= 0) { 
      return urlList.get(current);
    }
    return null;
  }

  public void pushURL(URL url) { 
    if (url != null) { 
      if (current < (urlList.size() - 1)) {
	for (int i = urlList.size() - 1; i > current; i--) {
	  urlList.remove(i);
	}
      }
      urlList.add(url); 
      current++;

      //System.out.println("  HTMLPane current=" + current + " urlList.size()=" + urlList.size()); 
      if (frame != null) { 
	frame.updateButtonState();
      }
    }
  }

  public void setResourceURL(String resourceURL) {
    if (resourceURL != null) {
      try {
	URL url = HTMLPane.class.getResource(resourceURL);
	setURL(url);
      } catch (Exception e) {
      }
    }
  }

  public void setURL(String surl) {
    if (surl != null) {
      try {
	URL url = new URL(surl); 
	setURL(url);
      } catch (Exception e) {
      }
    }
  }

  public void setURL(URL url) {
    if (url != null) {
      try {
	URL currentURL = getCurrentURL(); 
	if (!url.equals(currentURL)) { 
	  html.setPage(url);
	  pushURL(url);
	}
      } catch (IOException e) {
	System.out.println("IOException: " + e);
      }
    }
  }

  public void scrollToReference(String reference) {
    if (reference != null) {
      html.scrollToReference(reference);
      try { 
	URL currentURL = getCurrentURL(); 
	URL newURL = new URL(currentURL, "#" + reference);
	if (!newURL.equals(currentURL)) { 
	  pushURL(newURL);
	}
      } catch (Exception e) {}
    }
  }

  public void setText(String text) {
    html.setText(text);
  }

  public boolean canForward() { 
    return (current < (urlList.size() - 1));
  }

  public boolean canBack() { 
    return (current > 0);
  }

  public void forward() {
    if (current < (urlList.size() - 1)) { 
      try {
	URL url = urlList.get(++current);
	html.setPage(url);
      } catch (IOException e) {
	System.out.println("IOException: " + e);
      }
      if (frame != null) { 
	frame.updateButtonState();
      }
    }
  }

  public void back() { 
    if (current > 0) { 
      try {
	URL url = urlList.get(--current);
	html.setPage(url);
      } catch (IOException e) {
	System.out.println("IOException: " + e);
      }
      if (frame != null) { 
	frame.updateButtonState();
      }
    }

  }

  static public HyperlinkListener createHyperLinkListener(HTMLPane target) {
    return new SimpleHyperlinkListener(target);
  }

  static class SimpleHyperlinkListener 
    implements HyperlinkListener {

    HTMLPane target; 

    SimpleHyperlinkListener(HTMLPane target) {
      this.target = target; 
    }

    public void hyperlinkUpdate(HyperlinkEvent e) {
      if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
	if (e instanceof HTMLFrameHyperlinkEvent) {
	  HTMLDocument doc = (HTMLDocument) target.getEditorPane().getDocument();
	  doc.processHTMLFrameHyperlinkEvent((HTMLFrameHyperlinkEvent) e);
	} else {
	  URL url = e.getURL();
	  //System.out.println("SimpleHyperlinkListener.hyperlinkUpdate(): " + url);
	  target.setURL(url);
	}
      }
    }
  }

  /**
   * main method allows us to run as a standalone demo.
   */
  public static void main(String[] args) {
    HTMLPane demo = new HTMLPane();
    JFrame frame = new JFrame();
    frame.setContentPane(demo);
    frame.setSize(600, 400);
    frame.setVisible(true);

    /*
     * if (args.length > 0 && args[0] != null) { demo.setURL(args[0]); }
     * 
     * URL url = null; // System.getProperty("user.dir") + //
     * System.getProperty("file.separator"); String path = null; try { path =
     * "/resources/oview/index.html"; url = getClass().getResource(path);
     * 
     * //path = "http://venus.cs.depaul.edu/se452/se452.html"; //path =
     * "file:///home/jia/Courses/SE452/se452.html"; //url = new URL(path); }
     * catch (Exception e) { System.err.println("Failed to open " + path);
     * url = null; }
     * 
     */
  }

}
